"""
通知服务 - 发送发布和回滚相关的通知
"""
import logging
import smtplib
import requests
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from typing import Dict, Any, List, Optional
from datetime import datetime

from app.core.config import current_settings
from app.models.release import Release

logger = logging.getLogger(__name__)


class NotificationService:
    """通知服务类"""
    
    def __init__(self):
        self.email_config = self._get_email_config()
        self.webhook_config = self._get_webhook_config()
    
    async def send_deployment_start_notification(self, release: Release):
        """发送发布开始通知"""
        try:
            message = self._format_deployment_start_message(release)
            await self._send_notification("发布开始", message, "info")
        except Exception as e:
            logger.error(f"发送发布开始通知失败: {e}")
    
    async def send_deployment_success_notification(self, release: Release):
        """发送发布成功通知"""
        try:
            message = self._format_deployment_success_message(release)
            await self._send_notification("发布成功", message, "success")
        except Exception as e:
            logger.error(f"发送发布成功通知失败: {e}")
    
    async def send_deployment_failure_notification(self, release: Release):
        """发送发布失败通知"""
        try:
            message = self._format_deployment_failure_message(release)
            await self._send_notification("发布失败", message, "error")
        except Exception as e:
            logger.error(f"发送发布失败通知失败: {e}")
    
    async def send_rollback_success_notification(self, release: Release, target_release: Release):
        """发送回滚成功通知"""
        try:
            message = self._format_rollback_success_message(release, target_release)
            await self._send_notification("回滚成功", message, "success")
        except Exception as e:
            logger.error(f"发送回滚成功通知失败: {e}")
    
    async def send_rollback_failure_notification(self, release: Release, target_release: Release, error: str):
        """发送回滚失败通知"""
        try:
            message = self._format_rollback_failure_message(release, target_release, error)
            await self._send_notification("回滚失败", message, "error")
        except Exception as e:
            logger.error(f"发送回滚失败通知失败: {e}")
    
    async def send_emergency_notification(self, title: str, message: str):
        """发送紧急通知"""
        try:
            await self._send_notification(title, message, "emergency")
        except Exception as e:
            logger.error(f"发送紧急通知失败: {e}")
    
    async def _send_notification(self, title: str, message: str, level: str = "info"):
        """发送通知"""
        # 发送邮件通知
        if self.email_config.get("enabled"):
            await self._send_email_notification(title, message, level)
        
        # 发送Webhook通知
        if self.webhook_config.get("enabled"):
            await self._send_webhook_notification(title, message, level)
        
        # 发送钉钉通知
        if current_settings.ALERT_WEBHOOK:
            await self._send_dingtalk_notification(title, message, level)
    
    async def _send_email_notification(self, title: str, message: str, level: str):
        """发送邮件通知"""
        try:
            if not self.email_config.get("smtp_server"):
                return
            
            msg = MIMEMultipart()
            msg['From'] = self.email_config["from_email"]
            msg['To'] = ", ".join(self.email_config["to_emails"])
            msg['Subject'] = f"[{level.upper()}] {title}"
            
            # 添加HTML内容
            html_content = self._format_email_html(title, message, level)
            msg.attach(MIMEText(html_content, 'html', 'utf-8'))
            
            # 发送邮件
            with smtplib.SMTP(self.email_config["smtp_server"], self.email_config["smtp_port"]) as server:
                if self.email_config.get("use_tls"):
                    server.starttls()
                
                if self.email_config.get("username") and self.email_config.get("password"):
                    server.login(self.email_config["username"], self.email_config["password"])
                
                server.send_message(msg)
            
            logger.info(f"邮件通知发送成功: {title}")
            
        except Exception as e:
            logger.error(f"邮件通知发送失败: {e}")
    
    async def _send_webhook_notification(self, title: str, message: str, level: str):
        """发送Webhook通知"""
        try:
            webhook_url = self.webhook_config.get("url")
            if not webhook_url:
                return
            
            payload = {
                "title": title,
                "message": message,
                "level": level,
                "timestamp": datetime.now().isoformat(),
                "source": "saas-deploy-system"
            }
            
            response = requests.post(
                webhook_url,
                json=payload,
                headers={"Content-Type": "application/json"},
                timeout=10
            )
            
            if response.status_code == 200:
                logger.info(f"Webhook通知发送成功: {title}")
            else:
                logger.error(f"Webhook通知发送失败: {response.status_code} - {response.text}")
                
        except Exception as e:
            logger.error(f"Webhook通知发送失败: {e}")
    
    async def _send_dingtalk_notification(self, title: str, message: str, level: str):
        """发送钉钉通知"""
        try:
            webhook_url = current_settings.ALERT_WEBHOOK
            
            # 根据级别设置颜色
            color_map = {
                "info": "blue",
                "success": "green",
                "error": "red",
                "emergency": "red"
            }
            color = color_map.get(level, "blue")
            
            payload = {
                "msgtype": "markdown",
                "markdown": {
                    "title": title,
                    "text": f"## {title}\n\n{message}\n\n**级别**: {level.upper()}\n**时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
                },
                "at": {
                    "isAtAll": level in ["error", "emergency"]
                }
            }
            
            response = requests.post(
                webhook_url,
                json=payload,
                headers={"Content-Type": "application/json"},
                timeout=10
            )
            
            if response.status_code == 200:
                logger.info(f"钉钉通知发送成功: {title}")
            else:
                logger.error(f"钉钉通知发送失败: {response.status_code} - {response.text}")
                
        except Exception as e:
            logger.error(f"钉钉通知发送失败: {e}")
    
    def _format_deployment_start_message(self, release: Release) -> str:
        """格式化发布开始消息"""
        return f"""
发布任务已开始执行

**版本**: {release.version}
**环境**: {release.environment}
**策略**: {release.strategy}
**描述**: {release.description or '无'}
**发布人**: {release.deployed_by}
**开始时间**: {release.deployed_at.strftime('%Y-%m-%d %H:%M:%S') if release.deployed_at else 'N/A'}

请关注发布进度，如有异常将自动回滚。
        """.strip()
    
    def _format_deployment_success_message(self, release: Release) -> str:
        """格式化发布成功消息"""
        duration = ""
        if release.deployed_at and release.completed_at:
            duration = (release.completed_at - release.deployed_at).total_seconds()
            duration = f"**耗时**: {duration:.2f}秒\n"
        
        return f"""
发布任务执行成功

**版本**: {release.version}
**环境**: {release.environment}
**策略**: {release.strategy}
**发布人**: {release.deployed_by}
**开始时间**: {release.deployed_at.strftime('%Y-%m-%d %H:%M:%S') if release.deployed_at else 'N/A'}
**完成时间**: {release.completed_at.strftime('%Y-%m-%d %H:%M:%S') if release.completed_at else 'N/A'}
{duration}

新版本已成功部署到生产环境。
        """.strip()
    
    def _format_deployment_failure_message(self, release: Release) -> str:
        """格式化发布失败消息"""
        return f"""
发布任务执行失败

**版本**: {release.version}
**环境**: {release.environment}
**策略**: {release.strategy}
**发布人**: {release.deployed_by}
**开始时间**: {release.deployed_at.strftime('%Y-%m-%d %H:%M:%S') if release.deployed_at else 'N/A'}

系统将自动回滚到上一个稳定版本，请检查发布日志。
        """.strip()
    
    def _format_rollback_success_message(self, release: Release, target_release: Release) -> str:
        """格式化回滚成功消息"""
        return f"""
回滚任务执行成功

**回滚前版本**: {release.version}
**回滚后版本**: {target_release.version}
**环境**: {release.environment}
**回滚原因**: {release.rollback_reason}
**操作人**: {release.rollback_by}
**回滚时间**: {release.rollback_at.strftime('%Y-%m-%d %H:%M:%S') if release.rollback_at else 'N/A'}

系统已成功回滚到稳定版本。
        """.strip()
    
    def _format_rollback_failure_message(self, release: Release, target_release: Release, error: str) -> str:
        """格式化回滚失败消息"""
        return f"""
回滚任务执行失败

**回滚前版本**: {release.version}
**回滚目标版本**: {target_release.version}
**环境**: {release.environment}
**回滚原因**: {release.rollback_reason}
**错误信息**: {error}

请立即手动处理，系统可能处于不稳定状态。
        """.strip()
    
    def _format_email_html(self, title: str, message: str, level: str) -> str:
        """格式化邮件HTML内容"""
        color_map = {
            "info": "#007bff",
            "success": "#28a745",
            "error": "#dc3545",
            "emergency": "#dc3545"
        }
        color = color_map.get(level, "#007bff")
        
        return f"""
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; }}
        .header {{ background-color: {color}; color: white; padding: 15px; border-radius: 5px; }}
        .content {{ background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin-top: 10px; }}
        .footer {{ margin-top: 20px; font-size: 12px; color: #6c757d; }}
    </style>
</head>
<body>
    <div class="header">
        <h2>{title}</h2>
    </div>
    <div class="content">
        <pre style="white-space: pre-wrap; font-family: inherit;">{message}</pre>
    </div>
    <div class="footer">
        <p>此邮件由SaaS平台发布与回滚系统自动发送</p>
        <p>发送时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
    </div>
</body>
</html>
        """.strip()
    
    def _get_email_config(self) -> Dict[str, Any]:
        """获取邮件配置"""
        return {
            "enabled": bool(current_settings.ALERT_EMAIL),
            "smtp_server": "smtp.example.com",
            "smtp_port": 587,
            "use_tls": True,
            "username": "noreply@example.com",
            "password": "your-password",
            "from_email": "noreply@example.com",
            "to_emails": current_settings.ALERT_EMAIL.split(",") if current_settings.ALERT_EMAIL else []
        }
    
    def _get_webhook_config(self) -> Dict[str, Any]:
        """获取Webhook配置"""
        return {
            "enabled": False,
            "url": "https://webhook.example.com/notify"
        }

